package edu.stthomas.seis752.controllers;


import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import edu.stthomas.seis752.form.NewCrewForm;
import edu.stthomas.seis752.form.UserForm;
import edu.stthomas.seis752.model.Collection;
import edu.stthomas.seis752.model.CollectionType;
import edu.stthomas.seis752.model.Location;
import edu.stthomas.seis752.model.Member;
import edu.stthomas.seis752.model.User;
import edu.stthomas.seis752.service.LocationService;
import edu.stthomas.seis752.service.UserService;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {

	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

	@Autowired
	private UserService userService;
	
	@Autowired
	private LocationService locationService;
	
	@Autowired
	private Validator validator;
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		return "home";
	}
	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public String login(Locale locale, Model model) {
		return "login";
	}
	
	@RequestMapping(value = "/logout", method = RequestMethod.GET)
	public String logout(){
	    SecurityContextHolder.getContext().getAuthentication().setAuthenticated(false);
	    SecurityContextHolder.getContext().setAuthentication(null);
	    return "login";
	}
	
	@RequestMapping(value = "/testdb", method = RequestMethod.GET)
	public String testdb(Locale locale, Model model) {
		logger.info("Welcome to test DB");
		User user = userService.getUser(1L);
		if(user != null){
			logger.info("User retrieved:" + user.getUserName());
			model.addAttribute("userName", user.getUserName());
		}
		else{
			logger.info("User object is null!");
			model.addAttribute("userName", "null");
		}

		return "home";
	}

	@RequestMapping(value = "/createUser", method = RequestMethod.POST)
	public ModelAndView registerUser(@ModelAttribute("userform") UserForm userForm,
			BindingResult result) {

		System.out.println("Name:" + userForm.getFirstName() + " / User Name:"
				+ userForm.getUserName() + " / Fav location: " + userForm.getFavoriteLocation() + " / Profile pic: " + userForm.getProfilePic());
		
		this.validator.validate(userForm, result);
        if (result.hasErrors()) {
            System.out.println("have errors");
            return showContacts(new UserForm());
        } 
        
        User newUser = new User(userForm.getUserName(), userForm.getPassword(), new Date());
        newUser.setFirstName(userForm.getFirstName());
        newUser.setLastName(userForm.getLastName());
        if(StringUtils.hasLength(userForm.getAge())) newUser.setAge(Integer.valueOf(userForm.getAge()));
        Location favLoc = locationService.getLocation(Long.valueOf(userForm.getFavoriteLocation()));
        newUser.setFavoriteLocation(favLoc);
		userService.addUser(newUser, userForm.getProfilePic());
		
		// TODO authenticate this user that was just created
		return new ModelAndView("login");
	}

	@RequestMapping(value = "/createUser", method = RequestMethod.GET)
	public ModelAndView showContacts(@ModelAttribute("userform") UserForm userForm) {

        Map<String,String> favoriteLocations = new LinkedHashMap<String,String>();
        List<Location> locations = locationService.getLocations(10);
        for(Location loc : locations ){
        	favoriteLocations.put("" + loc.getId(), loc.getName());
        }
		
        ModelAndView mav = new ModelAndView("createUser");
        mav.addObject("locationList", favoriteLocations);
        
        return mav;

	}
	
	@RequestMapping(value = "/mycrews", method = RequestMethod.GET)
	public ModelAndView showMyCrews(@ModelAttribute("newCrewForm") NewCrewForm form) {
		
		return createMyCrewsView();
	}
	
	public ModelAndView createMyCrewsView(){
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
	    String name = auth.getName();
	    User currUser = userService.getUserByUserName(name);
	    
		List<Collection> crews = userService.getCollectionsForOwner(currUser.getId());
		
		ModelAndView mav = new ModelAndView("mycrews");
        mav.addObject("mycrewlist", crews);
        
        Map<String,String> memberOptions = new LinkedHashMap<String,String>();
        List<User> users = userService.getUsers(20);// limit 20 for now
        for(User u : users ){
        	if(!u.getId().equals(currUser.getId())){
        		// make sure the current user is not returned (once session persistence available)
            	memberOptions.put("" + u.getId(), u.getFirstName() + " " + u.getLastName());
        	}
        }
		
        mav.addObject("memberOptions", memberOptions);
        
        return mav;
	}
	
	@RequestMapping(value = "/mycrews/remove", method = RequestMethod.POST)
	public String removeCrew(@RequestParam("crew") long crewId) {
		
	    Collection c = (Collection)userService.getPersistedObject(Collection.class, crewId);
	    
	    userService.remove(c);
	    
	    return "redirect:/mycrews";
	}
	
	@RequestMapping(value = "/mycrews", method = RequestMethod.POST)
	public ModelAndView addNewCrew(@ModelAttribute("newCrewForm") NewCrewForm form,
			BindingResult result) {

		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
	    String name = auth.getName();
	    User currUser = userService.getUserByUserName(name);
	    
		Collection crew = new Collection();
		CollectionType type = userService.getCollectionType("CRC");
		crew.setCollectionType(type);
		crew.setName(form.getName());
		crew.setOwnerId(currUser.getId()); // use current user
		
		crew = userService.addCollection(crew);
		
		for(String userId : form.getMembers()){
			Member m = new Member();
			User u = userService.getUser(new Long(userId));
			m.setUser(u);
			m.setCollection(crew);
			userService.saveMember(m);
		}
		
		return createMyCrewsView();
	}
	
	// this is to prove database works with new APIs
	@RequestMapping(value = "/list/{rows}", method = RequestMethod.GET)
	public String list(@PathVariable String rows, Model model){
		List<User> result = userService.getUsers(Integer.parseInt(rows));
		List<String> list = new ArrayList();
		for(User user : result){
			if(user != null)
				list.add(user.getUserName());
		}
		model.addAttribute("list", list);
		return "listusers";
	}
}
